home *** CD-ROM | disk | FTP | other *** search
- /*
- * A more or less BSD compatable socket library for MacTCP
- *
- * Summer 1989, Tom Milligan, University of Toronto Computing Services
- */
-
- #include <Events.h>
- #include <types.h>
- #include <memory.h>
- #include <stdio.h>
- #include <OSUtils.h> /* for SysBeep */
-
- /* unixincludes */
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/errno.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
- #include <sys/uio.h>
- #include <net/if.h>
-
- #include "tcpglue.h"
- #include "socket.internal.h"
-
- /*
- * sock_init() - initialize everything.
- */
- sock_init()
- {
- OSErr io;
- int i;
-
- if (sockets != NULL)
- return;
-
- #if SOCK_UTIL_DEBUG >= 2
- dprintf("sock_init: first time through\n");
- dprintf("sock_init: allocating %d bytes for %d socket records\n",
- NUM_SOCKETS * sizeof(SocketRecord),NUM_SOCKETS);
- #endif
-
- /* allocate storage for socket records */
- sockets = (SocketPtr)NewPtr(NUM_SOCKETS * sizeof(SocketRecord));
- if (sockets == NULL)
- return(sock_err(ENOMEM));
- bzero(sockets, NUM_SOCKETS * sizeof(SocketRecord));
-
- /* initialize them */
- for (i=0; i<NUM_SOCKETS; i++)
- {
- sock_clear_fd(i);
- }
-
- /* load the MacTCP name server resolver */
- #if SOCK_UTIL_DEBUG >= 2
- dprintf("sock_init: loading name server resolver\n");
- #endif
-
- io = OpenResolver(NULL);
-
- #if SOCK_UTIL_DEBUG >= 1
- if (io != noErr)
- dprintf("sock_init: failed to load name server resolver code %d\n",io);
- #endif
- }
-
- /*
- * sock_close_all() - Close all sockets (aborting their connections) and
- * release dynamic storage.
- */
- sock_close_all()
- {
- int s;
- SocketPtr sp;
-
- for (s = 0 ; s < NUM_SOCKETS ; ++s)
- {
- sp = &sockets[s];
- if (sp->status == SOCK_STATUS_USED)
- {
- switch(sp->protocol)
- {
- case IPPROTO_UDP:
- (void) xUDPRelease(&sp->pb);
- break;
-
- case IPPROTO_TCP:
- (void) xTCPRelease(&sp->pb.tcp);
- break;
- }
- sock_clear_fd(s);
- }
- }
- DisposPtr((Ptr)sockets);
-
- /* release name server resources */
- (void) CloseResolver();
- }
-
- /*
- * sock_free_fd()
- *
- * Get the next free file descriptor >= f. Return -1 if none available.
- */
- sock_free_fd(f)
- int f;
- {
- int s;
-
- for (s = f; s < NUM_SOCKETS; s++)
- if (! is_used(&sockets[s]))
- return(s);
- return(-1);
- }
-
- /*
- * sock_dup_fd() - duplicate a socket table entry.
- */
- sock_dup_fd(s,s1)
- {
- BlockMove((Ptr)&sockets[s], (Ptr)&sockets[s1], sizeof(SocketRecord));
- sock_init_fd(s1);
- }
-
- /*
- * sock_clear_fd() - Clear out a socket table entry freeing any
- * storage attached to it.
- *
- * Then re-initialize it for reuse.
- */
- sock_clear_fd(s)
- int s;
- {
- SocketPtr sp = &sockets[s];
- int i;
-
- for (i=0; i<TCP_MAX_WRITES; i++)
- {
- if (sp->wpb[i].wds[0].ptr != NULL)
- DisposPtr(sp->wpb[i].wds[0].ptr);
- }
- bzero(sp, sizeof(SocketRecord));
- sp->sa.sin_family = AF_UNSPEC;
- sp->status &= ~SOCK_STATUS_USED;
-
- sock_init_fd(s);
- }
-
- sock_init_fd(s)
- int s;
- {
- SocketPtr sp = &sockets[s];
- int i;
-
- sp->fd = s;
- sp->apb.sp = sp;
- for (i=0; i<TCP_MAX_WRITES; i++)
- sp->wpb[i].sp = sp;
- }
-
-
- /*
- * sock_alloc_wds_buf() - allocate a new buffer if the old one is too
- * small or if there isn't one yet
- */
- static Ptr
- sock_alloc_wds_buf(sp,len)
- SocketPtr sp;
- unsigned short len;
- {
- if (sp->wpb[sp->nextwpb].wds[0].ptr != NULL)
- {
- if (GetPtrSize(sp->wpb[sp->nextwpb].wds[0].ptr) < len)
- {
- DisposPtr(sp->wpb[sp->nextwpb].wds[0].ptr);
- sp->wpb[sp->nextwpb].wds[0].ptr = NULL;
- }
- }
- if (sp->wpb[sp->nextwpb].wds[0].ptr == NULL)
- {
- len = max(len,536);
- sp->wpb[sp->nextwpb].wds[0].ptr = NewPtr(len);
- if (sp->wpb[sp->nextwpb].wds[0].ptr == nil)
- return(NULL);
- }
- return(sp->wpb[sp->nextwpb].wds[0].ptr);
- }
-
- /*
- * sock_buf_to_wds() - build a one-entry macTCP wds
- */
- sock_buf_to_wds(sp, buffer, len)
- SocketPtr sp;
- char *buffer;
- int len;
- {
- if (!goodptr(buffer))
- return(sock_err(EFAULT));
-
- switch(sp->protocol)
- {
- case IPPROTO_UDP:
- if (len <= 0 || len > UDP_MAX_MSG)
- return(sock_err(EINVAL));
- break;
-
- case IPPROTO_TCP:
- if (len <= 0 || len > TCP_MAX_MSG)
- return(sock_err(EINVAL));
- break;
- }
-
- if (sock_alloc_wds_buf(sp,len) == NULL)
- return(sock_err(ENOMEM));
-
- BlockMove(buffer,sp->wpb[sp->nextwpb].wds[0].ptr,len);
- sp->wpb[sp->nextwpb].wds[0].length = len;
- sp->wpb[sp->nextwpb].wds[1].length = 0;
- return(len);
- }
-
- /*
- * sock_iov_to_wds() - mash an iov into a one-entry macTCP wds
- */
- sock_iov_to_wds(sp,iov, count)
- SocketPtr sp;
- struct iovec *iov;
- int count;
- {
- int i;
- struct iovec *v;
- unsigned long len;
- Ptr p;
-
- len = 0;
- for (v=iov, i=0; i<count; i++, v++)
- {
- if (!goodptr(v->iov_base))
- return(sock_err(EFAULT));
-
- switch(sp->protocol)
- {
- case IPPROTO_UDP:
- if (v->iov_len < 0 || v->iov_len > UDP_MAX_MSG)
- return(sock_err(EINVAL));
- len += v->iov_len;
- if (len > UDP_MAX_MSG)
- return(sock_err(EINVAL));
- break;
-
- case IPPROTO_TCP:
- if (v->iov_len < 0 || v->iov_len > TCP_MAX_MSG)
- return(sock_err(EINVAL));
- len += v->iov_len;
- if (len > TCP_MAX_MSG)
- return(sock_err(EINVAL));
- break;
- }
- }
-
- if (sock_alloc_wds_buf(sp,len) == NULL)
- return(sock_err(ENOMEM));
-
- p = sp->wpb[sp->nextwpb].wds[0].ptr;
- for (v=iov, i=0; i<count; i++, v++)
- {
- BlockMove(v->iov_base,p,v->iov_len);
- p += v->iov_len;
- }
- sp->wpb[sp->nextwpb].wds[0].length = len;
- sp->wpb[sp->nextwpb].wds[1].length = 0;
- return(len);
- }
-
- /*
- * sock_err() - Socket error. Set errno and show debugging info.
- */
- sock_err(err_code)
- int err_code;
- {
- errno = err_code;
- #if SOCK_UTIL_DEBUG >= 1
- dprintf("SOCK error %d\n", errno);
- #endif
- return(-1);
- }
-
- /*
- * valid_file_ptr
- *
- * Make sure the file pointer "sp" points to one of the entrys in the
- * socket table and that that entry is in use.
- * Return the file descriptor if valid, or -1 if invalid.
- *
- * dont print anything. this can be called from interrupt level.
- */
- valid_file_ptr(sp)
- SocketPtr sp;
- {
- int s;
-
- for(s = 0; s < NUM_SOCKETS; s++)
- {
- if (&sockets[s] == sp)
- {
- if (is_used(sp))
- return(s);
- else
- return(-1);
- }
- }
- }
-
-
- /*
- * sock_copy_addr
- */
- sock_copy_addr(from,to,tolen)
- struct sockaddr_in *from;
- struct sockaddr_in *to;
- int *tolen;
- {
- *tolen = min(*tolen, sizeof(struct sockaddr_in));
- BlockMove((Ptr)from, (Ptr)to, *tolen);
- }
-
-
- #if SOCK_UTIL_DEBUG > 1
- /*
- * print the socket records.
- */
- sock_dump()
- {
- int s;
- char title[20];
-
- for (s=0; s<NUM_SOCKETS; s++)
- {
- if (! is_used(&sockets[s]))
- continue;
- sprintf(title,"%2d",s);
- sock_print(title,&sockets[s]);
- }
- }
-
- sock_print(title,sp)
- char *title;
- SocketPtr sp;
- {
- dprintf("%s: %08x %s %08x addr %08x/%d %08x/%d state %d/%d err %d\n",
- title, sp,
- (sp->protocol == IPPROTO_UDP ? "udp" : "tcp"),
- (sp->protocol == IPPROTO_UDP ? sp->pb.udp.udpStream : sp->pb.tcp.tcpStream),
- sp->sa.sin_addr.s_addr,sp->sa.sin_port,
- sp->peer.sin_addr.s_addr,sp->peer.sin_port,
- sp->sstate,xTCPState(&sp->pb),
- sp->asyncerr);
- }
- #endif
-
-